import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Checkbox } from 'antd';
import keyBy from 'lodash/keyBy';
import reject from 'lodash/reject';

const useSpecialCheck = (allRows, filterCheckable, checkKey = 'id') => {
    // 所有可勾选的行数据
    const [allCheckableRows, setAllCheckableRows] = useState([]);
    // 已经选择的数据
    const [selectedRows, setSelectedRows] = useState([]);
    // 基于【所有可勾选的行数据】建立Map<id,row>的map
    const allCheckableRowsMap = useMemo(() => keyBy(allCheckableRows, checkKey), [allCheckableRows]);
    // 基于【已经选择的数据】建立Map<id,row>的map
    const selectedRowsMap = useMemo(() => keyBy(selectedRows, checkKey), [selectedRows]);

    useEffect(() => {
        setAllCheckableRows(allRows.filter(filterCheckable));
        setSelectedRows([]);
    }, [allRows]);

    const CheckBoxTitle = ({ className, style = {}, ...otherProps }) => {
        const onChange = useCallback(
            event => {
                const { checked } = event.target;

                if (checked) {
                    setSelectedRows([...allCheckableRows]);
                } else {
                    setSelectedRows([]);
                }
            },
            [allRows]
        );

        const indeterminate = useMemo(
            () =>
                allCheckableRows.length > 0 && selectedRows.length > 0 && allCheckableRows.length > selectedRows.length,
            [allCheckableRows, selectedRows]
        );

        const checked = useMemo(() => allCheckableRows.length === selectedRows.length && allCheckableRows.length > 0, [
            allCheckableRows,
            selectedRows
        ]);

        return (
            <Checkbox
                indeterminate={indeterminate}
                checked={checked}
                onChange={onChange}
                className={className}
                style={style}
                {...otherProps}
            />
        );
    };
    CheckBoxTitle.displayName = 'CheckBoxTitle';

    const CheckboxCell = ({ record, className, style = {}, ...otherProps }) => {
        const onChange = useCallback(
            event => {
                const { checked } = event.target;

                let newSelected = [...selectedRows];
                if (checked) {
                    newSelected.push(allCheckableRowsMap[record[checkKey]]);
                } else {
                    newSelected = reject(newSelected, item => item[checkKey] === record[checkKey]);
                }
                setSelectedRows(newSelected);
            },
            [allRows, record]
        );

        const checked = useMemo(() => !!selectedRowsMap[record[checkKey]], [selectedRows, record]);

        return (
            <Checkbox
                value={record[checkKey]}
                onChange={onChange}
                checked={checked}
                className={className}
                style={style}
                {...otherProps}
            />
        );
    };

    CheckboxCell.displayName = 'CheckboxCell';

    return {
        CheckBoxTitle,
        CheckboxCell,
        allCheckableRows,
        selectedRows
    };
};

export default useSpecialCheck;
